#!/usr/bin/env python
# -*- coding: UTF-8 -*-

'''
Created on Feb 26, 2016

@author: liul32

'''

import os
import time
import sys
import argparse
from subprocess import PIPE, Popen

def which(program):
    def is_exe(fpath):
        flag = os.path.isfile(fpath) and os.access(fpath, os.X_OK)
        return flag
    
    fpath, fname = os.path.split(program)
    if fpath:
        if is_exe(program):
            return program

    else:
        for path in os.environ["PATH"].split(os.pathsep):
            path = path.strip('"')
            exe_file = os.path.join(path,program)
            if is_exe(exe_file):
                return exe_file
            
    return None

class AccurevError(Exception):
    '''
    
    AccurevError class captures the error of accurev commands execution
    '''
    def __init__(self, value, stderr = None, returncode = None):
        self.value = value
        self.stderr = stderr
        self.returncode = returncode

class AccurevCommand(object):
    '''
    AccurevCommand class generates accurev command object based on 'accurev' commands
    '''
    def __init__(self, cwd = None, **params):
        if len(params) != 0:
            self.params = params
        self.accurev_exec = which('ac')
        if cwd is None and self.params['ws_path']:
            self.cwd = self.params['ws_path']
        else:
            self.cwd = cwd
        if not self.accurev_exec:
            print "Cannot find accurev executable"
    
    def run(self, timeout=300):
        run_command = [self.accurev_exec] + self.command
        #print(run_command, self.cwd)
        process = Popen(run_command, stdout = PIPE, stderr = PIPE, cwd = self.cwd)
        out, err = process.communicate()
        errorcode = process.returncode
        if errorcode != 0:
            print "Find Error Messages: \n"+err
            #raise AccurevError(out,err,errorcode)
        return (errorcode, out, err)
    
    def ac_purge(self): 
        if self.params['stream'] and self.params['purgeFile']:
            stream = self.params['stream']
            files = self.params['purgeFile']
            self.command = ['purge', '-s', stream, files]
            errorcode, out, err = self.run()
            if errorcode == 0:
                return True
            else:
                print "Fail to purge {0} on stream {1}".format(files, stream)
                return False
        else : 
            print "[Parameter Errors] Miss parameters of stream or purge files"
            return False
    
    def ac_stat_overlap(self):
        if self.params['stream']:
            stream = self.params['stream']
            self.command = ['stat','-o','-s',stream,'-fl']
            errorcode, out, err = self.run()
            if errorcode == 0:
                return (out, True)
        else:
            print "[Parameter Errors] Miss parameter of stream"
            return False
        

    def ac_merge(self, overlap_file):
        if self.params['stream']:
            stream = self.params['stream']
            filename = overlap_file
            self.command = ['merge', '-s', stream, filename,'-K']   
            errorcode, out, err = self.run()
            if errorcode == 0:
                print "[Success] successfully auto-merge trivial overlap file {0}!".format(filename)
                return True
            else:
                print "[Error] find non-trivial overlap file {0}!".format(filename)
                return False
        else:
            print "[Parameter Errors] Miss parameters of stream"
            return False
        
if __name__ == '__main__':
    parser = argparse.ArgumentParser(prog = 'auto_merge.py')
    parser.add_argument('--workspace', action = 'store', dest = 'ws_path',help = 'add workspace path based on target stream', required = True)
    parser.add_argument('--target_stream', action = 'store', dest = 'stream', help = 'add target stream needs to merge overlaps', required = True)
    parser.add_argument('--purge_file', action = 'store', dest = 'purge_file', help = 'add file name needs to purge before merge', default = 'Version.xml')
    params = parser.parse_args()
    accurev_obj = AccurevCommand(ws_path = params.ws_path, stream = params.stream, purgeFile = params.purge_file)         
    overlaps, tag_overlap = accurev_obj.ac_stat_overlap()
    overlap_list = overlaps.splitlines(True)
    tag_purge = True
    tag_merge = False
    keep_file_count = 0
    nonTrivial_list = []
    if tag_overlap and 'Version.xml' in overlaps:
        tag_purge = accurev_obj.ac_purge()
        if tag_purge:
            overlap_list.remove('Version.xml')
    if tag_overlap and len(overlap_list) > 0:
        for overlap_file in overlap_list:
            tag_merge = accurev_obj.ac_merge(overlap_file.rstrip())
            if tag_merge == True:
                keep_file_count += 1
            else:
                nonTrivial_list.append(overlap_file)
        if len(overlap_list) == keep_file_count + len(nonTrivial_list):
            print(nonTrivial_list)
